package cn.sell.bpmn.test;

import cn.sell.bpmn.run.entity.StartProcess;
import lombok.extern.log4j.Log4j2;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.util.io.InputStreamSource;
import org.activiti.engine.impl.util.io.StreamSource;
import org.activiti.engine.impl.util.io.StringStreamSource;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.junit.Test;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 部署流程图
 */
@Log4j2
//@Service
//@Transactional
public class ActivitiDemo {

//    @Autowired
//    public RepositoryService repositoryService; //与流程定义和部署相关的service

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    String bpmn = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<bpmn2:definitions xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:bpmn2=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:activiti=\"http://activiti.org/bpmn\" id=\"diagram_Process_1634036751937\" targetNamespace=\"http://activiti.org/bpmn\" xsi:schemaLocation=\"http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd\">\n" +
            "  <bpmn2:process id=\"Process_1634036751937\" name=\"业务流程_1634036751937\" isExecutable=\"true\">\n" +
            "    <bpmn2:endEvent id=\"Event_1wdfh9t\">\n" +
            "      <bpmn2:incoming>Flow_1wy79zr</bpmn2:incoming>\n" +
            "      <bpmn2:incoming>Flow_0rsnsnj</bpmn2:incoming>\n" +
            "    </bpmn2:endEvent>\n" +
            "    <bpmn2:startEvent id=\"Event_18i6fwf\">\n" +
            "      <bpmn2:outgoing>Flow_05diemr</bpmn2:outgoing>\n" +
            "    </bpmn2:startEvent>\n" +
            "    <bpmn2:receiveTask id=\"Activity_1ddaygm\">\n" +
            "      <bpmn2:incoming>Flow_1jhbdm2</bpmn2:incoming>\n" +
            "      <bpmn2:outgoing>Flow_1099lb2</bpmn2:outgoing>\n" +
            "    </bpmn2:receiveTask>\n" +
            "    <bpmn2:exclusiveGateway id=\"Gateway_1sov3dg\">\n" +
            "      <bpmn2:incoming>Flow_1099lb2</bpmn2:incoming>\n" +
            "      <bpmn2:outgoing>Flow_0lizb8b</bpmn2:outgoing>\n" +
            "      <bpmn2:outgoing>Flow_1ge696x</bpmn2:outgoing>\n" +
            "    </bpmn2:exclusiveGateway>\n" +
            "    <bpmn2:userTask id=\"Activity_11tc3vj\">\n" +
            "      <bpmn2:incoming>Flow_1ge696x</bpmn2:incoming>\n" +
            "      <bpmn2:outgoing>Flow_1wy79zr</bpmn2:outgoing>\n" +
            "    </bpmn2:userTask>\n" +
            "    <bpmn2:userTask id=\"Activity_1nf28we\" activiti:candidateGroups=\"group6,group5\">\n" +
            "      <bpmn2:incoming>Flow_0lizb8b</bpmn2:incoming>\n" +
            "      <bpmn2:outgoing>Flow_0rsnsnj</bpmn2:outgoing>\n" +
            "    </bpmn2:userTask>\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_1099lb2\" sourceRef=\"Activity_1ddaygm\" targetRef=\"Gateway_1sov3dg\" />\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_0lizb8b\" sourceRef=\"Gateway_1sov3dg\" targetRef=\"Activity_1nf28we\">\n" +
            "      <bpmn2:conditionExpression xsi:type=\"bpmn2:tFormalExpression\">${pass==1}</bpmn2:conditionExpression>\n" +
            "    </bpmn2:sequenceFlow>\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_1ge696x\" sourceRef=\"Gateway_1sov3dg\" targetRef=\"Activity_11tc3vj\">\n" +
            "      <bpmn2:conditionExpression xsi:type=\"bpmn2:tFormalExpression\">${pass==0}</bpmn2:conditionExpression>\n" +
            "    </bpmn2:sequenceFlow>\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_1wy79zr\" sourceRef=\"Activity_11tc3vj\" targetRef=\"Event_1wdfh9t\" />\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_0rsnsnj\" sourceRef=\"Activity_1nf28we\" targetRef=\"Event_1wdfh9t\" />\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_05diemr\" sourceRef=\"Event_18i6fwf\" targetRef=\"Activity_1i9bejy\" />\n" +
            "    <bpmn2:sequenceFlow id=\"Flow_1jhbdm2\" sourceRef=\"Activity_1i9bejy\" targetRef=\"Activity_1ddaygm\" />\n" +
            "    <bpmn2:serviceTask id=\"Activity_1i9bejy\" activiti:class=\"cn.sell.bpmn.listener.ActivitiListenner\">\n" +
            "      <bpmn2:incoming>Flow_05diemr</bpmn2:incoming>\n" +
            "      <bpmn2:outgoing>Flow_1jhbdm2</bpmn2:outgoing>\n" +
            "    </bpmn2:serviceTask>\n" +
            "  </bpmn2:process>\n" +
            "  <bpmndi:BPMNDiagram id=\"BPMNDiagram_1\">\n" +
            "    <bpmndi:BPMNPlane id=\"BPMNPlane_1\" bpmnElement=\"Process_1634036751937\">\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_1099lb2_di\" bpmnElement=\"Flow_1099lb2\">\n" +
            "        <di:waypoint x=\"500\" y=\"200\" />\n" +
            "        <di:waypoint x=\"500\" y=\"235\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_0lizb8b_di\" bpmnElement=\"Flow_0lizb8b\">\n" +
            "        <di:waypoint x=\"525\" y=\"260\" />\n" +
            "        <di:waypoint x=\"630\" y=\"260\" />\n" +
            "        <di:waypoint x=\"630\" y=\"320\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_1ge696x_di\" bpmnElement=\"Flow_1ge696x\">\n" +
            "        <di:waypoint x=\"475\" y=\"260\" />\n" +
            "        <di:waypoint x=\"380\" y=\"260\" />\n" +
            "        <di:waypoint x=\"380\" y=\"320\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_1wy79zr_di\" bpmnElement=\"Flow_1wy79zr\">\n" +
            "        <di:waypoint x=\"380\" y=\"400\" />\n" +
            "        <di:waypoint x=\"380\" y=\"480\" />\n" +
            "        <di:waypoint x=\"482\" y=\"480\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_0rsnsnj_di\" bpmnElement=\"Flow_0rsnsnj\">\n" +
            "        <di:waypoint x=\"630\" y=\"400\" />\n" +
            "        <di:waypoint x=\"630\" y=\"480\" />\n" +
            "        <di:waypoint x=\"518\" y=\"480\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_05diemr_di\" bpmnElement=\"Flow_05diemr\">\n" +
            "        <di:waypoint x=\"500\" y=\"-52\" />\n" +
            "        <di:waypoint x=\"500\" y=\"0\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNEdge id=\"Flow_1jhbdm2_di\" bpmnElement=\"Flow_1jhbdm2\">\n" +
            "        <di:waypoint x=\"500\" y=\"80\" />\n" +
            "        <di:waypoint x=\"500\" y=\"120\" />\n" +
            "      </bpmndi:BPMNEdge>\n" +
            "      <bpmndi:BPMNShape id=\"Activity_0f50x4d_di\" bpmnElement=\"Activity_1ddaygm\">\n" +
            "        <dc:Bounds x=\"450\" y=\"120\" width=\"100\" height=\"80\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "      <bpmndi:BPMNShape id=\"Gateway_1tp8ctq_di\" bpmnElement=\"Gateway_1sov3dg\" isMarkerVisible=\"true\">\n" +
            "        <dc:Bounds x=\"475\" y=\"235\" width=\"50\" height=\"50\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "      <bpmndi:BPMNShape id=\"Event_1wdfh9t_di\" bpmnElement=\"Event_1wdfh9t\">\n" +
            "        <dc:Bounds x=\"482\" y=\"462\" width=\"36\" height=\"36\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "      <bpmndi:BPMNShape id=\"Activity_11tc3vj_di\" bpmnElement=\"Activity_11tc3vj\">\n" +
            "        <dc:Bounds x=\"330\" y=\"320\" width=\"100\" height=\"80\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "      <bpmndi:BPMNShape id=\"Activity_1nf28we_di\" bpmnElement=\"Activity_1nf28we\">\n" +
            "        <dc:Bounds x=\"580\" y=\"320\" width=\"100\" height=\"80\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "      <bpmndi:BPMNShape id=\"Event_18i6fwf_di\" bpmnElement=\"Event_18i6fwf\">\n" +
            "        <dc:Bounds x=\"482\" y=\"-88\" width=\"36\" height=\"36\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "      <bpmndi:BPMNShape id=\"Activity_17fbgdf_di\" bpmnElement=\"Activity_1i9bejy\">\n" +
            "        <dc:Bounds x=\"450\" y=\"0\" width=\"100\" height=\"80\" />\n" +
            "      </bpmndi:BPMNShape>\n" +
            "    </bpmndi:BPMNPlane>\n" +
            "  </bpmndi:BPMNDiagram>\n" +
            "</bpmn2:definitions>";

    @Test
    public void DeploymentProcessDefinition() {
        Deployment deployment = processEngine.getRepositoryService() //第二种获取方式 与流程定义和部署相关的service
                .createDeployment() // 创建一个部署对象
//                .name("流程引擎测试") // 添加部署的名称，
//                .addClasspathResource("processes/helloworld.bpmn") // 从class path中加载部署文件，一次只能加载一个
//                .addClasspathResource("processes/helloworld.png") // 从class path中加载部署文件，一次只能加载一个
//                .addZipInputStream("processes/helloworld.zip") // 从class path中加载zip部署文件
                .addString("test_bpmn.bpmn", bpmn) // 流程图字符串部署
                .deploy();// 完成部署
        System.out.println("部署ID：" + deployment.getId());
        System.out.println("部署名称：" + deployment.getName());

        /**
         * 返回的id为 1
         * 对应act_re_product表中的id为1的数据
         */
        /**
         * 操作的表如下：
         *
         * act_re_deployment（用来存储部署时需要持久化保存下来的信息）、act_re_procdef(业务流程定义数据表)、act_ge_bytearray（资源文件表：查看流程图时使用）
         * act_ge_property (主键生成策略表)
         *
         * act_re_deployment（部署表：用来存储部署时需要持久化保存下来的信息）
         * 存放流程定义的显示名和部署时间，每部署一次增加一条记录
         * 1.	ID_:部署编号，自增长
         * 2.	NAME_:部署包的名称（流程定义名称：默认为空需要设置）
         * 3.	DEPLOY_TIME_:部署时间
         *
         * act_re_procdef(流程定义表：业务流程定义数据表)
         * 存放流程定义的属性信息，部署每个新的流程定义都会在这张表中增加一条记录。
         * 注意：当流程定义的key相同的情况下，使用的是版本升级
         * 1.	ID_:流程定义ID，由“流程编号：流程版本号：自增长ID”组成
         * 2.	CATEGORY_:流程命名空间（该编号就是流程文件targetNamespace的属性值）
         * 3.	NAME_:流程定义名称（该编号就是流程文件process元素的name属性值）对应bpmn中的流程名称
         * 4.	KEY_:流程编号（该编号就是流程文件process元素的id属性值）
         * 5.	VERSION_:流程版本号（由程序控制，新增即为1，修改后依次加1来完成的，新增修改由key值决定，key已经存在版本加1，否则为1初始版本号）
         * 6.	DEPLOYMENT_ID_:部署编号
         * 7.	RESOURCE_NAME_:资源文件名称
         * 8.	DGRM_RESOURCE_NAME_:图片资源文件名称
         * 9.	HAS_START_FROM_KEY_:是否有Start From Key
         * 注：此表和ACT_RE_DEPLOYMENT是多对一的关系，即，一个部署的bar包里可能包含多个流程定义文件，每个流程定义文件都会有一条记录在ACT_REPROCDEF表内，
         * 每个流程定义的数据，都会对于ACT_GE_BYTEARRAY表内的一个资源文件和PNG图片文件。和ACT_GE_BYTEARRAY的关联是通过程序用ACT_GE_BYTEARRAY.NAME与ACT_RE_PROCDEF.NAME_完成的，
         * 在数据库表结构中没有体现。
         *
         * ACT_GE_BYTEARRAY(资源文件表：用来保存部署文件的大文本数据)
         * 存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录，
         * 一条是关于bpmn规则文件的，一条是图片的（如果部署时只指定了bpmn一个文件，activiti会在部署时解析bpmn文件内容自动生成流程图）。
         * 两个文件不是很大，都是以二进制形式存储在数据库中。
         * 1.	ID_:资源文件编号，自增长
         * 2.	REV_INT:版本号
         * 3.	NAME_:资源文件名称
         * 4.	DEPLOYMENT_ID_:来自于父表ACT_RE_DEPLOYMENT的主键
         * 5.	BYTES_:大文本类型，存储文本字节流
         */
    }

    @Test
    public void queryDeploymentProcess() {
        List<ProcessDefinition> list = processEngine.getRepositoryService() //第二种获取方式 与流程定义和部署相关的service
                .createProcessDefinitionQuery()
                //查询条件
//                .processDefinitionId("123")
                // 排序
                .orderByProcessDefinitionVersion().asc()
//                .listPage(10,1);
//                .count();
                .list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println("id：" + processDefinition.getId());
            System.out.println("name：" + processDefinition.getName());
            System.out.println("key：" + processDefinition.getKey());
            System.out.println("version：" + processDefinition.getVersion());
            System.out.println("deploymentId：" + processDefinition.getDeploymentId());
            System.out.println("category：" + processDefinition.getCategory());
            System.out.println("description：" + processDefinition.getDescription());
            System.out.println("diagramResourceName：" + processDefinition.getDiagramResourceName());
            System.out.println("resourceName：" + processDefinition.getResourceName());
            System.out.println("tenantId：" + processDefinition.getTenantId());
            System.out.println("engineVersion：" + processDefinition.getEngineVersion());
            System.out.println("=============================================================");
        }
    }

    /**
     * 启动指定流程
     * 使用key启动默认使用流程的最新版本启动
     */
    @Test
    public void startProcessInstance() {
        String processInstanceByKey = "helloworld";
// 2 启动流程
        //启动流程实例，同时设置流程变量，用来指定组任务的办理人
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("userIDs", "大大,小小,中中");

        ProcessInstance processInstance = processEngine.getRuntimeService() // 与正在执行的流程实例和执行对象相关的service
                .startProcessInstanceByKey("Process_1634036751937",variables);// 使用流程定义的key来启动流程实例 key对应bpmn文件中的id属性，act_re_product表中的key
        StartProcess startProcess = new StartProcess();
        startProcess.setUserId("123123123");
        startProcess.setBusinessKey("sdafasfsadfadfs");
        // 设置流程发起者，代理人
        Authentication.setAuthenticatedUserId(startProcess.getUserId());
        processEngine.getRuntimeService().setVariable(processInstance.getId(),"startProcess", startProcess);

        System.out.println("流程实例id：" + processInstance.getId());
        System.out.println("流程定义id：" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例名称：" + processInstance.getName());
        /**
         * 流程实例id：52501
         * 流程定义id：Process_1634036751937:4:47503
         * 流程实例名称：null
         */
        /**
         * 操作数据库的act_ru_execution表,如果是用户任务节点，同时也会在act_ru_task添加一条记录
         * 在activiti任务中，主要分为两大类查询任务（个人任务和组任务）：
         * 1.确切指定了办理者的任务，这个任务将成为指定者的私有任务，即个人任务。
         * 2.无法指定具体的某一个人来办理的任务，可以把任务分配给几个人或者一到	多个小组，让这个范围内的用户可以选择性（如有空余时间时）来办理这类任务，即组任务。
         * 先知道个人任务的查询和办理，组任务的操作后面讲
         *
         * 操作的表如下：
         *
         * act_ru_task(运行时任务数据表，任务表)、act_ru_execution(执行对象表)、act_ru_identitylink(流程用户表)、ACT_RU_VARIABLE(运行时流程变量数据表)
         * act_hi_actinst(存放历史所有完成的活动)、act_hi_identitylink()、act_hi_procinst(流程实例的历史表，存放执行完毕的流程实例信息)、act_hi_taskinst(已经执行完的历史任务信息)
         *
         * ACT_RU_TASK(运行时任务数据表，任务表)
         * 1.	ID_：7505
         * 2.	REV_： 1
         * 3.	EXECUTION_ID_： 执行实例的id      (7502)
         * 4.	PROC_INST_ID_： 流程实例的id      (7501)
         * 5.	PROC_DEF_ID_：  流程定义的id,对应act_re_procdef 的id_    (helloworld:3:5003)
         * 6.	NAME_：  任务名称，对应 ***task 的name       (提交申请)
         * 7.	PARENT_TASK_ID_ : 对应父任务
         * 8.	DESCRIPTION_：
         * 9.	TASK_DEF_KEY_： ***task 的id(节点id)        (usertask1)
         * 10.	OWNER_	: 发起人
         * 11.	ASSIGNEE_： 分配到任务的人(张三)
         * 12.	DELEGATION_ :  委托人
         * 13.	PRIORITY_： 紧急程度
         * 14.	CREATE_TIME_： 发起时间      (2021-10-11 00:58:09.727)
         * 15.	DUE_TIME_：审批时长
         *
         * ACT_RU_EXECUTION：
         * 1.	ID_：
         * 2.	REV_：版本号
         * 3.	PROC_INST_ID_：流程实例编号
         * 4.	BUSINESS_KEY_：业务编号
         * 5.	PARENT_ID_：找到该执行实例的父级，最终会找到整个流程的执行实例
         * 6.	PROC_DEF_ID_：流程ID
         * 7.	SUPER_EXEC_： 引用的执行模板
         * 8.	ACT_ID_：	节点id
         * 9.	IS_ACTIVE_： 是否访问
         * 10.	IS_CONCURRENT_：
         * 11.	IS_SCOPE_：
         *
         * ACT_RU_IDENTITYLINK(任务参与者数据表。主要存储当前节点参与者的信息)
         * 1.	ID_：  标识
         * 2.	REV_： 版本
         * 3.	GROUP_ID_： 组织id
         * 4.	TYPE_： 类型
         * 5.	USER_ID_： 用户id
         * 6.	TASK_ID_： 任务id
         *
         * ACT_RU_VARIABLE(运行时流程变量数据表)
         * 1.	ID_：标识
         * 2.	REV_：版本号
         * 3.	TYPE_：数据类型
         * 4.	NAME_：变量名
         * 5.	EXECUTION_ID_： 执行实例id
         * 6.	PROC_INST_ID_： 流程实例id
         * 7.	TASK_ID_： 任务id
         * 8.	BYTEARRAY_ID_：
         * 9.	DOUBLE_：若数据类型为double ,保存数据在此列
         * 10.	LONG_： 若数据类型为Long保存数据到此列
         * 11.	TEXT_： string 保存到此列
         * 12.	TEXT2_：
         */
    }

    @Test
    public void queryVariable(){
        String executionId = "52501";
        Object userIDs = processEngine.getRuntimeService().getVariable(executionId, "userIDs");
        StartProcess startProcess = (StartProcess)processEngine.getRuntimeService().getVariable("52501", "startProcess");
        System.out.println("userIDs:"+userIDs.toString());
        System.out.println("userIDs:"+startProcess.toString());
    }

    /**
     * 查询流程状态
     */
    @Test
    public void queryProcessStatus(){
        String processInstanceId = "52501";
        ProcessInstance processInstance = processEngine.getRuntimeService()
                .createProcessInstanceQuery() // 创建流程实例查询，查询正在执行的流程实例
                .processInstanceId(processInstanceId) // 按照流程实例id查询
                .singleResult();// 返回唯一结果集
        if(processInstance !=null){
            System.out.println("getId：" + processInstance.getId());
            System.out.println("getName：" + processInstance.getName());
            System.out.println("getProcessInstanceId：" + processInstance.getProcessInstanceId());
            System.out.println("getProcessDefinitionId：" + processInstance.getProcessDefinitionId());
            System.out.println("getProcessDefinitionKey：" + processInstance.getProcessDefinitionKey());
            System.out.println("getBusinessKey：" + processInstance.getBusinessKey());
            System.out.println("getDeploymentId：" + processInstance.getDeploymentId());
            System.out.println("getDescription：" + processInstance.getDescription());
            System.out.println("getProcessDefinitionName：" + processInstance.getProcessDefinitionName());
            System.out.println("getActivityId：" + processInstance.getActivityId());
        }else{
            System.out.println("流程实例已经结束");
        }
    }

    /**
     * 查询当前人的个人任务
     */
    @Test
    public void getMyPersonalTask() {
        String assignee = "王五";
        List<Task> list = processEngine.getTaskService()
                .createTaskQuery()//创建任务的查询对象
//                .processDefinitionKey("")
//                .taskAssignee(assignee) // 指定个人任务查询，指定办理人
                .list();
        for (Task task : list) {
            System.out.println("任务ID：" + task.getId());
            System.out.println("任务名称：" + task.getName());
            System.out.println("任务创建时间：" + task.getCreateTime());
            System.out.println("任务创建人：" + task.getAssignee());
            System.out.println("流程实例ID：" + task.getProcessInstanceId());
            System.out.println("执行对象ID：" + task.getExecutionId());
            System.out.println("流程定义ID：" + task.getProcessDefinitionId());
            System.out.println("============================================");
        }
        /**
         * 操作的表如下：
         *
         * act_ru_task(运行时任务数据表，任务表)
         **/
    }

    /*完成任务*/
    @Test
    public void completeMyPersonalTask() {
        String taskId = "12502";
        processEngine.getTaskService()
                .complete(taskId);
        /**
         * act_ru_task(运行时任务数据表，任务表)、act_ru_execution(执行对象表)、act_ru_identitylink(流程用户表)、ACT_RU_VARIABLE(运行时流程变量数据表)
         */
    }

    /**
     * 方法一：生成流程图；带进度:<br>
     * 得到带有高亮节点的流程图
     *
     * @param
     *            流程实例id
     * @return
     */
    @Test
    public void traceProcessImage() throws IOException {


        String processInstanceId = "37501";
        if (processInstanceId == null) {
            throw new ActivitiIllegalArgumentException(
                    "No process instance id provided");
        }

        ExecutionEntity pi = (ExecutionEntity) ProcessEngines.getDefaultProcessEngine().getRuntimeService()
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();

        if (pi == null) {
            throw new ActivitiObjectNotFoundException(
                    "Process instance with id" + processInstanceId
                            + " could not be found", org.activiti.api.process.model.ProcessInstance.class);
        }

        ProcessDefinitionEntity pde = (ProcessDefinitionEntity) ((RepositoryServiceImpl) ProcessEngines.getDefaultProcessEngine().getRepositoryService())
                .getDeployedProcessDefinition(pi.getProcessDefinitionId());

        if (pde != null && pde.isGraphicalNotationDefined()) {
            BpmnModel bpmnModel = ProcessEngines.getDefaultProcessEngine().getRepositoryService().getBpmnModel(pde.getId());

            List<String> activeActivityIds = ProcessEngines.getDefaultProcessEngine().getRuntimeService().getActiveActivityIds(processInstanceId);


            InputStream inputStream = new DefaultProcessDiagramGenerator().generateDiagram(
                    bpmnModel,
                    new ArrayList<String>(),
                    activeActivityIds,
                    pde.getDeploymentId(),
                    "宋体",
                    "宋体",
                    false,
                    pde.getResourceName());

            BufferedImage img = ImageIO.read(inputStream);
            ImageIO.write( img, "jpg", new File("H:\\text.bpmn"));

        } else {
            throw new ActivitiException("Process instance with id "
                    + processInstanceId + " has no graphic description");
        }
    }
}
